/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools fs struct definition
 */

#ifndef HMFS_FS_H
#define HMFS_FS_H

#include <string>
#include <sys/types.h>

#include "constant.h"
#include "hmfs_quota.h"
#include "hmfs_utils.h"

namespace OHOS {
namespace Hmfs {
struct HmfsDevice {
    char path[DEVICE_PATH_MAX_LEN];
    uint32_t segmentCount;
}__attribute__((packed));

/*
 * Super block area, data is writed in little-ending
 */
struct SuperBlockData {
    uint32_t magicNumber;
    uint16_t majorVersion;
    uint16_t minorVersion;
    uint32_t logSectorSize;
    uint32_t log2SectorsPerBlock;
    uint32_t logBlockSize;
    uint32_t logBlksPerSeg;
    uint32_t segsPerSection;
    uint32_t sectionsPerZone;
    uint32_t checksumOffset;
    uint64_t blockCount;
    uint32_t sectionCount;
    uint32_t segmentCount;
    uint32_t segmentCountInCP;
    uint32_t segmentCountInSIT;
    uint32_t segmentCountInNAT;
    uint32_t segmentCountInSSA;
    uint32_t segmentCountInMain;
    uint32_t segment0BlockId;
    uint32_t checkPointBlockId;
    uint32_t sitBlockId;
    uint32_t natBlockId;
    uint32_t ssaBlockId;
    uint32_t mainBlockId;
    uint32_t rootInodeId;
    uint32_t nodeInodeId;
    uint32_t metaInodeId;
    uint8_t uuid[UUID_SIZE];
    uint16_t volumeName[VOLUME_NAME_MAX_LEN];
    uint32_t coldExtensionCount;
    char extensionList[EXTENSION_COUNT_MAX][EXTENSION_LEN_MAX];
    uint32_t checkPointPayload;
    uint8_t version[VERSION_TOTAL_LEN];
    uint8_t initVersion[VERSION_TOTAL_LEN];
    uint32_t features;
    uint8_t encryptionLevel;
    uint8_t encryptionSalt[ENCRYPTION_SALT_SIZE];
    HmfsDevice devices[MAX_DEVICE_COUNT];
    uint32_t quotaInodeId[MAX_QUOTAS];
    uint8_t hotExtensionCount;
    uint16_t encoding;
    uint16_t encodingFlags;
    uint8_t stopReason[CP_STOP_REASON_MAX];
    uint8_t errors[HMFS_MAX_ERRORS];
    uint8_t reserved[SUPER_BLOCK_RESERVED_SIZE];
    uint32_t checksum;
}__attribute__((packed));

/*
 * Sit area
 */
struct SitEntry {
    uint16_t usedBlocks;
    uint8_t blockBitmap[SIT_BITMAP_SIZE];
    uint64_t modificationTime;
} __attribute__((packed));

struct SitBlockData {
    SitEntry entries[SIT_ENTRIES_PER_BLOCK];
};

/*
 * Nat area
 */
struct NatEntry {
    uint8_t version;
    uint32_t inodeNumber;  
    uint32_t blockId;
} __attribute__((packed));

struct NatBlockData {
    NatEntry entries[NAT_ENTRIES_PER_BLOCK];
};

/*
 * Check point area
 */
struct CheckPointData {
    uint64_t checkPointVersion;
    uint64_t userBlockCount;
    uint64_t validBlockCount;
    uint32_t reservedSegmentCount;
    uint32_t overprovisionSegmentCount;
    uint32_t freeSegmentCount;

    uint32_t curNodeSegNo[HMFS_MAX_ACTIVE_NODE_LOGS];
    uint16_t curNodeBlkOffset[HMFS_MAX_ACTIVE_NODE_LOGS];
    uint32_t curDataSegNo[HMFS_MAX_ACTIVE_DATA_LOGS];
    uint16_t curDataBlkOffset[HMFS_MAX_ACTIVE_DATA_LOGS];
    uint32_t checkPointFlags;
    uint32_t checkPointPackBlockCount;
    uint32_t summaryStartBlock;
    uint32_t validNodeCount;
    uint32_t validInodeCount;
    uint32_t nextFreeNodeId;
    uint32_t sitVersionBitmapSize;
    uint32_t natVersionBitmapSize;
    uint32_t checksumOffset;
    uint64_t mountElapsedTime;
    uint8_t allocType[HMFS_MAX_ACTIVE_LOGS];
    uint8_t sitNatVersionBitmap[];
};

struct SummaryEntry {
    uint32_t nodeId;
    struct {
        uint8_t version;
        uint16_t nodeBlockOffset;
    } __attribute__((packed));
} __attribute__((packed));

struct NatJournalEntry {
    uint32_t nodeId;
    NatEntry natEntry;
} __attribute__((packed));

struct SummaryFooter {
    uint8_t entryType;
    uint32_t checkSum;
} __attribute__((packed));

struct NatJournal {
    NatJournalEntry entries[NAT_JOURNAL_ENTRY_COUNT];
    uint8_t reserved[NAT_JOURNAL_RESERVED_COUNT];
};

struct SitJournalEntry {
    uint32_t sitNumber;
    SitEntry sitEntry;
} __attribute__((packed));

struct SatJournal {
    SitJournalEntry entries[SIT_JOURNAL_ENTRY_COUNT];
    uint8_t reserved[SIT_JOURNAL_RESERVED_COUNT];
};

struct ExtraInfo {
    uint64_t totalBytesWritten;
    uint8_t reserved[EXTRA_INFO_RESERVED_SIZE];
} __attribute__((packed));

struct JournalEntry {
    union {
        uint16_t natCount;
        uint16_t sitCount;
    };
    union {
        NatJournal natJournalArray;
        SatJournal sitJournalArray;
        ExtraInfo info;
    };
} __attribute__((packed));

struct SummaryBlockData {
    SummaryEntry entries[ENTRY_COUNT_IN_SUM];
    JournalEntry journal;
    SummaryFooter footer;
};

struct HmfsExtent {
    uint32_t fileOffset;
    uint32_t blkAddr;
    uint32_t len;
} __attribute__((packed));

/*
 * Hmfs inode
 */
struct HmfsInode {
    uint16_t fileMode;
    uint8_t fileHints;
    uint8_t inlineFlags;
    uint32_t userId;
    uint32_t groupId;
    uint32_t linkCount;
    uint64_t fileSize;
    uint64_t blockSize;
    uint64_t accessTime;
    uint64_t changeTime;
    uint64_t modificationTime;
    uint32_t accessTimeNsec;
    uint32_t changeTimeNsec;
    uint32_t modificationTimeNsec;
    uint32_t fileVersion;
    union {
        uint32_t directoryDepth;
        uint16_t gcFailureCount;
    };
    uint32_t xattrNodeId;
    uint32_t fileAttributes;
    uint32_t parentInodeNumber;
    uint32_t fileNameLength;
    uint8_t fileName[HMFS_NAME_LEN];
    uint8_t directoryLevel;
    HmfsExtent largestExtent;

    union {
        struct {
            uint16_t extraInodeSize;
            uint16_t inlineXattrSize;
            uint32_t projectId;
            uint32_t inodeChecksum;
            uint64_t creationTime;
            uint32_t creationTimeNsec;
            uint64_t compressedBlockCount;
            uint8_t compressionAlgorithm;
            uint8_t logClusterSize;
            uint16_t padding;
            uint32_t extraEnd[0];
        } __attribute__((packed));
        uint32_t dataBlocksAddr[ADDR_COUNT_PER_INODE];
    };
    uint32_t nodeIds[NODE_ID_COUNT];
} __attribute__((packed));

struct DirectNode {
    uint32_t addr[DEF_ADDRS_PER_BLOCK];
};

struct IndirectNode {
    uint32_t nodeId[NIDS_PER_BLOCK];
};

struct NodeFooter {
    uint32_t nodeId;
    uint32_t inodeNumber;
    uint32_t flag;
    uint64_t checkPointVersion;
    uint32_t nextBlockAddr;
} __attribute__((packed));

struct NodeData {
    union {
        HmfsInode inode;
        DirectNode directNode;
        IndirectNode indirectNode;
    };
    NodeFooter footer;
};

struct DirEntry {
    uint32_t hashCode;
    uint32_t inodeNumber;
    uint16_t nameLength;
    uint8_t fileType;
} __attribute__((packed));

struct DentryBlock {
    uint8_t dentryBitmap[DENTRY_BITMAP_SIZE];
    uint8_t reserved[RESERVED_SIZE];
    DirEntry dentry[DENTRY_COUNT_IN_BLOCK];
    uint8_t filename[DENTRY_COUNT_IN_BLOCK][HMFS_SLOT_LEN];
};

inline uint32_t NatBlockOffset(uint32_t startNodeId)
{
    return startNodeId / NAT_ENTRY_PER_BLOCK;
}

inline uint16_t GetSitType(SitEntry *rawSit)
{
    return (LE16ToNative(rawSit->usedBlocks) & ~SIT_VBLOCKS_MASK) >> SIT_USER_BLOCK_COUNT_SHIFT;
}

inline uint32_t GetSitVblocks(SitEntry *rawSit)
{
    return (LE16ToNative(rawSit->usedBlocks) & SIT_VBLOCKS_MASK);
}
} // namespace Hmfs
} // namespace OHOS
#endif
